package com.wlz;

import com.wlz.vo.CalqtyCalcLedgerShardingModel;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class PageSubtotalGenerator {

    public static void main(String[] args) {
        //        List<main.java.CalqtyCalcLedgerShardingModel> data = Arrays.asList(
//                new main.java.CalqtyCalcLedgerShardingModel("A", "item1", new BigDecimal("1"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"), new BigDecimal("5")),
//                new main.java.CalqtyCalcLedgerShardingModel("A", "item2", new BigDecimal("10"), new BigDecimal("20"), new BigDecimal("30"), new BigDecimal("40"), new BigDecimal("50")),
//                new main.java.CalqtyCalcLedgerShardingModel("B", "item3", new BigDecimal("100"), new BigDecimal("200"), new BigDecimal("300"), new BigDecimal("400"), new BigDecimal("500"))
//        );
        List<CalqtyCalcLedgerShardingModel> input = new ArrayList<>();
        for (int i = 1; i <= 18; i++) {
            input.add(new CalqtyCalcLedgerShardingModel("A", "item1", new BigDecimal("1"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"), new BigDecimal("5")));
        }
        for (int i = 1; i <= 10; i++) {
            input.add(new CalqtyCalcLedgerShardingModel("B", "item2", new BigDecimal("10"), new BigDecimal("20"), new BigDecimal("30"), new BigDecimal("40"), new BigDecimal("50")));
        }

        List<CalqtyCalcLedgerShardingModel> result = process(input);
        print(result);
    }

    public static List<CalqtyCalcLedgerShardingModel> process(List<CalqtyCalcLedgerShardingModel> inputList) {
        final int PAGE_SIZE = 16;
        final int NORMAL_PAGE_DATA_SIZE = 15;
        final int LAST_CHAPTER_PAGE_DATA_SIZE = 14;
        final int FINAL_CHAPTER_PAGE_DATA_SIZE = 13;

        List<CalqtyCalcLedgerShardingModel> result = new ArrayList<>();
        BigDecimal[] totalSum = new BigDecimal[5];
        Arrays.fill(totalSum, BigDecimal.ZERO);

        Map<String, List<CalqtyCalcLedgerShardingModel>> chapterMap = inputList.stream()
                .collect(Collectors.groupingBy(CalqtyCalcLedgerShardingModel::getIsbn, LinkedHashMap::new, Collectors.toList()));

        int chapterIndex = 0;
        int chapterCount = chapterMap.size();

        for (Map.Entry<String, List<CalqtyCalcLedgerShardingModel>> entry : chapterMap.entrySet()) {
            String isbn = entry.getKey();
            List<CalqtyCalcLedgerShardingModel> chapterList = entry.getValue();
            List<CalqtyCalcLedgerShardingModel> chapterResult = new ArrayList<>();
            BigDecimal[] chapterSum = new BigDecimal[5];
            Arrays.fill(chapterSum, BigDecimal.ZERO);

            int cursor = 0;
            while (cursor + NORMAL_PAGE_DATA_SIZE <= chapterList.size()) {
                List<CalqtyCalcLedgerShardingModel> pageData = new ArrayList<>(chapterList.subList(cursor, cursor + NORMAL_PAGE_DATA_SIZE));
                BigDecimal[] pageSum = sum(pageData);
                pageData.add(new CalqtyCalcLedgerShardingModel("", "本页小计", pageSum, "本页小计"));
                chapterResult.addAll(pageData);
                addInPlace(chapterSum, pageSum);
                cursor += NORMAL_PAGE_DATA_SIZE;
            }

            List<CalqtyCalcLedgerShardingModel> lastPageData = new ArrayList<>();
            while (cursor < chapterList.size()) lastPageData.add(chapterList.get(cursor++));
            boolean isLastChapter = (++chapterIndex == chapterCount);
            int requiredDataSize = isLastChapter ? FINAL_CHAPTER_PAGE_DATA_SIZE : LAST_CHAPTER_PAGE_DATA_SIZE;

            while (lastPageData.size() < requiredDataSize) lastPageData.add(blank(isbn));
            BigDecimal[] lastPageSum = sum(lastPageData);
            lastPageData.add(new CalqtyCalcLedgerShardingModel("", "本页小计", lastPageSum, "本页小计"));
            addInPlace(chapterSum, lastPageSum);
            lastPageData.add(new CalqtyCalcLedgerShardingModel("", "本章小计", chapterSum, "本章小计"));
            addInPlace(totalSum, chapterSum);

            if (isLastChapter) {
                lastPageData.add(new CalqtyCalcLedgerShardingModel("合计", "合计", totalSum, "合计"));
            }

            chapterResult.addAll(lastPageData);
            result.addAll(chapterResult);
        }

        int fill = PAGE_SIZE - (result.size() % PAGE_SIZE);
        if (fill < PAGE_SIZE) for (int i = 0; i < fill; i++) result.add(blank(""));

        return result;
    }

    private static CalqtyCalcLedgerShardingModel blank(String isbn) {
        return new CalqtyCalcLedgerShardingModel("", "", null, null, null, null, null);
    }

    private static BigDecimal[] sum(List<CalqtyCalcLedgerShardingModel> list) {
        BigDecimal[] sums = new BigDecimal[5];
        Arrays.fill(sums, BigDecimal.ZERO);
        for (CalqtyCalcLedgerShardingModel m : list) {
            if (m.getMoney1() != null) sums[0] = sums[0].add(m.getMoney1());
            if (m.getMoney2() != null) sums[1] = sums[1].add(m.getMoney2());
            if (m.getMoney3() != null) sums[2] = sums[2].add(m.getMoney3());
            if (m.getMoney4() != null) sums[3] = sums[3].add(m.getMoney4());
            if (m.getMoney5() != null) sums[4] = sums[4].add(m.getMoney5());
        }
        return sums;
    }

    private static void addInPlace(BigDecimal[] target, BigDecimal[] add) {
        for (int i = 0; i < 5; i++) {
            target[i] = target[i].add(add[i]);
        }
    }

    private static void print(List<CalqtyCalcLedgerShardingModel> list) {
        int index = 1;
        for (CalqtyCalcLedgerShardingModel item : list) {
            log.info("Index:{} | ISBN: {} | Name: {} | M1:{} M2:{} M3:{} M4:{} M5:{} | Remark: {}",
                    index++, item.getIsbn(), item.getName(),
                    item.getMoney1(), item.getMoney2(), item.getMoney3(), item.getMoney4(), item.getMoney5(),
                    item.getRemark());
        }
    }
}
